/*
 *
 *  Created by John David Duncan on 6/25/09.
 *  Copyright 2009 Sun Microsystems. All rights reserved.
 *
 */


/*
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; version 2 of the License.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 */


/* This is a C source file, because the callback functions registered
   as visitors are C functions called by InnoDB.
*/

#include <stdio.h>
#include <stdlib.h>
#include "innodb.h"

/* externs */
extern int show_sys_cols;

void describe_col_type(ib_col_type_t col_type, ib_ulint_t len,
                       ib_col_attr_t attr) {
  switch(col_type) {
    case IB_SYS:
      printf("SYSTEM(%lu)  ", len);
      break;
    case IB_VARCHAR:
    case IB_VARCHAR_ANYCHARSET:
      if(len == 0) printf("TEXT");
      else printf("varchar(%lu) ", len);    
      break;
    case IB_CHAR:
    case IB_CHAR_ANYCHARSET:
      printf("char(%lu)    ", len);
      break;
    case IB_NOT_USED1:
    case IB_NOT_USED2:
    case IB_NOT_USED5:
      printf("RESERVED[%d]", col_type);
      break;
    case IB_INT: 
      printf("int(%lu)     ", len);
      break;
    case IB_FLOAT:
      printf("float        ");
      break;
    case IB_DOUBLE:
      printf("double       "); 
      break;
    case IB_BLOB:
      printf("BLOB(%lu)    ", len);
      break;
    default:
      printf("strange column [%d]! ", col_type);
  }
  
  if(attr && IB_COL_UNSIGNED) printf("UNSIGNED ");
  if(attr && IB_COL_NOT_NULL) printf("NOT NULL ");  
}


int visit_describe_table(void *a, const char *name, ib_tbl_fmt_t tbl_fmt,
                   ib_ulint_t pgsize, int n_col, int n_idx) {
  char *formats[4] = { "Redundant", "Compact", "Dynamic", "Compressed" };
    
  printf("%s \t\tFormat: %s \t", name,  formats[(int) tbl_fmt]);
  if(pgsize) printf(" Page size: %lu", pgsize);
  printf("\n%d column%s, %d index%s\n\n", n_col, n_col == 1 ? "" : "s",
         n_idx, n_idx == 1 ? "" : "es");
    
  return 0;
}


int describe_col(void *a, const char* name, ib_col_type_t col_type,
                ib_ulint_t len,	ib_col_attr_t attr) {  
  if (col_type == IB_SYS && ! show_sys_cols) return 0;
  printf("%s ", name);
  describe_col_type(col_type, len, attr);  
  printf("\n");
  return 0;
}


int describe_index(void *a, const char* name, ib_bool_t pk, 
                   ib_bool_t unique, int n_cols) {
  printf("\n");
  if(pk) printf("Primary Key: ");
  else printf( "%sIndex %s: ", (unique ? "Unique " : ""), name);
  return 0;
}


int describe_index_col(void *a, const char * name, ib_ulint_t sz) {  
  printf("%s", name);
  if(sz) printf("(%lu)", sz);
  printf(" ");
  return 0;
}


int visit_table_null(void *x1, const char *x2, ib_tbl_fmt_t x3, ib_ulint_t x4,
                     int x5, int x6) {
  return 0;
}


const ib_schema_visitor_t visitor = {
  IB_SCHEMA_VISITOR_TABLE_AND_INDEX_COL,
  visit_describe_table,
  describe_col,
  describe_index,
  describe_index_col
};


const ib_schema_visitor_t test_visitor = {
  IB_SCHEMA_VISITOR_TABLE,
  visit_table_null
};


int describe_table(const char *name) {
  int err = DB_SUCCESS; 
  ib_trx_t trx = ib_trx_begin(IB_TRX_READ_COMMITTED);
  
  err = ib_schema_lock_exclusive(trx);
  if(err != DB_SUCCESS) goto cleanup;

  /* Run with the null visitor, just to catch "no such table" errors
     before really printing anything
  */
  err = ib_table_schema_visit(trx, name, &test_visitor, 0);
  if(err != DB_SUCCESS) goto cleanup;

  printf("\n");
  printf("---------------------------------------------------------------\n");
  err = ib_table_schema_visit(trx, name, &visitor, 0);    
  printf("\n");
  printf("---------------------------------------------------------------\n");

  cleanup:
  ib_trx_commit(trx);
  return err;
}

